package{

//import flash.xml.*;
import flash.utils.Dictionary;

import org.openzoom.flash.descriptors.IImagePyramidDescriptor;
import org.openzoom.flash.descriptors.IImagePyramidLevel;
import org.openzoom.flash.descriptors.IImageSourceDescriptor;
import org.openzoom.flash.descriptors.ImagePyramidDescriptorBase;
import org.openzoom.flash.descriptors.ImagePyramidLevel;
import org.openzoom.flash.descriptors.ImageSourceDescriptor;
import org.openzoom.flash.utils.math.clamp;

public final class EslideDescriptor extends ImagePyramidDescriptorBase
                           implements IImagePyramidDescriptor
{
    //--------------------------------------------------------------------------
    //
    //  Namespaces
    //
    //--------------------------------------------------------------------------
   
    private var rdf:Namespace = new Namespace ("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
	private var dc:Namespace = new Namespace ("http://purl.org/dc/elements/1.1/");
	private var dp:Namespace = new Namespace ("http://www.telemed.uniud.it/dp/0.1/");
	private var dcq:Namespace = new Namespace ("http://purl.org/dc/qualifiers/1.0/");
	
	namespace openzoom = "http://ns.openzoom.org/openzoom/2008"; //28/09/09

	//variables
	
	private var extension : String = "jpg";
    private var data : XML;
    private var levels : Dictionary = new Dictionary(); //28/09/09
    
	private var tileOverlapX : int = 32;
	private var tileOverlapY : int = 10;
	
	//11/09/09
	private var tileW : int;
	private var tileH : int;
	
	private var imgType : String;
	
	private var numLvl : int;
	
	private var imageWidth : int;
	private var imageHeight : int;
	
	public var maxZoom : Number; //17/09/09
	
	private var _sources:Array = []; //28/09/09
	
	
	/**
	 *  @inheritDoc
	 * /
	 */
	 //28/09/09
	 override public function get sources():Array
	 {
	 	return _sources.slice(0);
	 }
	
    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructor.
     */
     
    public function EslideDescriptor( uri : String, data:XML)
    {
        use namespace openzoom; //28/09/09
        
        this.data = data;
		this.source = uri;
		parseXML( data );
        //levels = computeLevels(numLvl);
    }
    
    private function parseXML (data:XML):void
    {
    	use namespace openzoom;
    	
    	// determine the number of zoom levels
    	var numDescr:int = data.children().length();
        numLvl = numDescr-2;
        this._numLevels = numLvl;
        
        //TODO implementare il ciclo "for each" (che diventerà for i=1; i<=numLvl; i++))
    	
    	var path:String = this.source.substring(0, this.source.lastIndexOf("/") + 1)
        var qqq=0;
        
        // determine maximum size of image pyramid
       
        //relation micron/pixel
		var micronX = data.rdf::Description.dp::resolution.dp::x;
		var micronY = data.rdf::Description.dp::resolution.dp::y;
		
		//tile size micron
		var imsizeX = data.rdf::Description.dp::imsize.dp::x;
		var imsizeY = data.rdf::Description.dp::imsize.dp::y;
		
		//gives tile size in pixel
		tileW = imsizeX;
        this._tileWidth = tileW; //14/09/09
        tileH = imsizeY;
        this._tileHeight = tileH; //14/09/09
        
        var rangeX = data.rdf::Description[1].dp::matrix.dp::xrange;
		var	nTileX:Array = rangeX.split("-");
		var columns = nTileX[1];
		var imgW:int = columns*tileW;
		
		var rangeY = data.rdf::Description[1].dp::matrix.dp::yrange;
		var	nTileY:Array = rangeY.split("-");
		var rows = nTileY[1];
		var imgH:int = rows*tileH;
		 
        imageWidth = imgW;
        this._width = imageWidth; //14/09/09
        imageHeight = imgH;
        this._height = imgH; //14/09/09
        
        //17/09/09
        // maximum Zoom allowed for the considered set (minimum zoom = 1, set in .mxml file)
        maxZoom = data.rdf::Description[1].dp::magnification;
        
        //23/09/09
        //this._origin = "Center"; 
        
        // determine (compute) image levels
        for (var index:int = numLvl -1; index >= 0; index--) 
        {
        	var level:XML = data.rdf::Description[index+1];
        	var pathLevelBuf =  level.attributes();
	    	var pathLevel = pathLevelBuf.substring(2);
			
        	//var uris:Array = [];
        	
        	var rngX = data.rdf::Description[index+1].dp::matrix.dp::xrange;
			var	nTX:Array = rngX.split("-");
			var lvlCol = nTX[1];
			var lvlW:int = lvlCol*tileW;
			
			var rngY = data.rdf::Description[index+1].dp::matrix.dp::yrange;
			var	nTY:Array = rngY.split("-");
			var lvlRow = nTY[1];
			var lvlH:int = lvlRow*tileH;
			
			/*
			// create ImageSourceDescriptor
			for (var sCol = 0; sCol<lvlCol; sCol++)
			{
				for (var sRow = 0; sRow<lvlRow; sRow++)
				{
					var sourceUri:String = [ path, pathLevel, sRow+1, "-", sCol+1, ".", extension ].join("") 
					var descriptor:IImageSourceDescriptor
					descriptor = new ImageSourceDescriptor(sourceUri, lvlW, lvlH, extension);
					_sources.push(descriptor);
				}
			}
			*/

        	var newIndex = (numLvl-1)-index % numLvl;
        	var imgLevel:ImagePyramidLevel = new ImagePyramidLevel(this,
        	    						   newIndex,
        	    						   lvlW,
        	    						   lvlH,
        	    						   lvlCol,
        	    						   lvlRow);
        	    						   
        	levels[newIndex] = imgLevel;
        	var cntr = 0;
        }
        
    }
    
    /*
    public function parseXML(data:XML):void
    {		
		//relation micron/pixel
		var micronX = data.rdf::Description.dp::resolution.dp::x;
		var micronY = data.rdf::Description.dp::resolution.dp::y;
		
		//tile size micron
		var imsizeX = data.rdf::Description.dp::imsize.dp::x;
		var imsizeY = data.rdf::Description.dp::imsize.dp::y;
		
		//gives tile size in pixel
		tileW = imsizeX;
        this._tileWidth = tileW; //14/09/09
        tileH = imsizeY;
        this._tileHeight = tileH; //14/09/09
        
        imgType = "jpg";
        this._type = imgType;
        
        var numDescr:int = data.children().length();
        
        numLvl = numDescr-2;
        this._numLevels = numLvl;
        
        var rangeX = data.rdf::Description[1].dp::matrix.dp::xrange;
		var	nTileX:Array = rangeX.split("-");
		var columns = nTileX[1];
		var imgW:int = columns*tileW;
		
		var rangeY = data.rdf::Description[1].dp::matrix.dp::yrange;
		var	nTileY:Array = rangeY.split("-");
		var rows = nTileY[1];
		var imgH:int = rows*tileH;
		 
        imageWidth = imgW;
        this._width = imageWidth; //14/09/09
        imageHeight = imgH;
        this._height = imgH; //14/09/09
        
        //17/09/09
        // maximum Zoom allowed for the considered set (minimum zoom = 1, set in .mxml file)
        maxZoom = data.rdf::Description[1].dp::magnification;
       
        //23/09/09
        //this._origin = "Center"; 
    }*/ //28/09/09
    
    public function getTileURL( level : int, column : int, row : int ) : String
    {
       
        var path : String  = this.source.substring( 0, source.length - 12 ) //12 = caseInfo.RDF
        //e.g. 'C:/prototipo_local/m021/5x/m0215x6-16.jpg';
    	//e.g. 'C:/prototipo_local/m021/10x/m02110x43-52.jpg
    	extension = "jpg";
        var actualLevel = data.rdf::Description[numLvl-level];
        var pathLevelBuf =  actualLevel.attributes();
    	
    	var pathLevel = pathLevelBuf.substring(2);
    	var completePath =  [ path, pathLevel, row+1, "-", column+1, ".", extension ].join("")
    	return completePath;
        
    }
	/* 
	public function computeLevels(nLev:int):Dictionary
	{
		var levels:Dictionary = new Dictionary()
		for (var ind:int = 0; ind<nLev; ind++)
		{
	        var rangeX = data.rdf::Description[ind+1].dp::matrix.dp::xrange;
			var	nTileX:Array = rangeX.split("-");
			var columns = nTileX[1];
			var imgWidth:int = columns*tileW;
			
			var rangeY = data.rdf::Description[ind+1].dp::matrix.dp::yrange;
			var	nTileY:Array = rangeY.split("-");
			var rows = nTileY[1];
			var imgHeight:int = rows*tileH;
			 
	        var newIndex:int = nLev-1-ind; 
	        
	        var level:ImagePyramidLevel = new ImagePyramidLevel(this,newIndex,imgWidth,imgHeight,columns,rows)
	        levels[newIndex] = level;
	        
        }
        return levels;   
	}*/ //28/09/09
	
    /**
     * @inheritDoc
     */
    
    public override function getLevelAt( index : int ) : IImagePyramidLevel
    {
        /*
        if (index >= numLvl)
        	{
        		clamp(index, 0, numLvl - 1);
        	}
       */
       return IImagePyramidLevel( levels[ index ] )
    } //28/09/09

    /**
     * @inheritDoc
     */
    /*
    public function getLevelForSize( width : Number,
                                        height : Number ) : IImagePyramidLevel
    {
    	var level : IImagePyramidLevel;
    	
    	for(var i : int = numLvl-1; i >=0; i--)
    	{
    		level = getLevelAt(i);
    		if(level.width < width || level.height < height ){ 
    			break;
    		}
    		
    	}
    
    	return getLevelAt( clamp(level.index+1,0,numLvl-1)).clone(); 
    	
    }*/ //28/09/09
    
    public function getLevelForSize (width : Number, height : Number) : IImagePyramidLevel
    {
    	var currentLevel:IImagePyramidLevel;
    	
    	for (var i:int = numLvl - 1; i>=0; i--)
    	//for (var i:int = 0; i<numLvl;i++) //29/09/09
    	{
    		currentLevel = getLevelAt(i);
    		if (currentLevel.width <= width || currentLevel.height <= height)
    			break
    	}
    	
    	var maxLevel:uint = numLvl - 1;
    	var index:int = clamp(i + 1, 0, maxLevel);
    	var level:IImagePyramidLevel = getLevelAt(index);
    	/*
    	if (width / level.width < 0.5)
    		level = getLevelAt(Math.max(0, index - 1))
    		
    	if (width / level.width < 0.5)
    		trace ("[EslideDescriptor] getLevelForSize():", width / level.width);
    	*/	
    	return level;
    }

    /**
     * @inheritDoc
     */
    public function clone() : IImagePyramidDescriptor
    {
    	//return new EslideDescriptor(source, new XML( data ) ); //28/09/09
    	
    	return new EslideDescriptor(source, data.copy());
    }
}
}
 
